# -*- coding: utf-8 -*-
#
# Copyright (c) 2025 Huawei Technologies Co., Ltd.
# openUBMC is licensed under Mulan PSL v2.
# You can use this software according to the terms and conditions of the Mulan PSL v2.
# You may obtain a copy of Mulan PSL v2 at:
#         http://license.coscl.org.cn/MulanPSL2
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
# See the Mulan PSL v2 for more details.

"""
统一代码生成器

提供统一的代码生成入口，协调各个子生成器。
"""

from typing import Optional, List, TYPE_CHECKING
from .context import CodeGenContext
from .registry import EmitterRegistry, get_global_registry
from .emitter import EmitResult

if TYPE_CHECKING:
    from ...ir import IRNode, IRModule


class CodeGenerator:
    """统一代码生成器

    提供统一的代码生成接口，管理生成器实例和上下文。
    """

    def __init__(self, registry: Optional[EmitterRegistry] = None):
        """初始化代码生成器

        Args:
            registry: 发射器注册表，如果为None则使用全局注册表
        """
        self.registry = registry or get_global_registry()
        self._expr_generator = None
        self._stmt_generator = None
        self._decl_generator = None

    def generate_expression(
        self,
        expr: "IRNode",
        context: Optional[CodeGenContext] = None,
        parent_precedence: int = 100,
        in_assignment: Optional[bool] = None,
        ir_module: Optional["IRModule"] = None,
    ) -> str:
        """生成表达式代码

        Args:
            expr: 表达式IR节点
            context: 代码生成上下文
            parent_precedence: 父表达式优先级
            in_assignment: 是否在赋值语句中（None表示从上下文继承）
            ir_module: IR模块

        Returns:
            str: 生成的C++表达式代码
        """
        # 创建或更新上下文
        if context is None:
            context = CodeGenContext(
                ir_module=ir_module,
                in_assignment=in_assignment if in_assignment is not None else False,
                parent_precedence=parent_precedence,
            )
        else:
            # 创建子上下文
            child_kwargs = {
                "current_node": expr,
                "parent_precedence": parent_precedence,
            }
            # 只有当明确指定了in_assignment时才覆盖，否则从上下文继承
            if in_assignment is not None:
                child_kwargs["in_assignment"] = in_assignment
            context = context.create_child_context(**child_kwargs)

        # 生成代码
        result = self._generate_node(expr, context)

        # 处理优先级和括号
        # 注意：使用 > 而不是 >=，因为相同优先级的左结合运算符不需要括号
        # 例如：a[b][c] 不需要写成 (a[b])[c]
        if result.precedence > parent_precedence:
            return f"({result.code})"
        return result.code

    def generate_statement(
        self,
        stmt: "IRNode",
        context: Optional[CodeGenContext] = None,
        ir_module: Optional["IRModule"] = None,
    ) -> str:
        """生成语句代码

        Args:
            stmt: 语句IR节点
            context: 代码生成上下文
            ir_module: IR模块

        Returns:
            str: 生成的C++语句代码
        """
        # 创建或更新上下文
        if context is None:
            context = CodeGenContext(ir_module=ir_module)
        else:
            context = context.with_node(stmt)

        # 生成代码
        result = self._generate_node(stmt, context)
        return result.code

    def generate_statements(
        self,
        statements: List["IRNode"],
        context: Optional[CodeGenContext] = None,
        return_type: str = "void",
        ir_module: Optional["IRModule"] = None,
    ) -> str:
        """生成语句块代码

        Args:
            statements: 语句IR节点列表
            context: 代码生成上下文
            return_type: 返回类型
            ir_module: IR模块

        Returns:
            str: 生成的C++语句块代码
        """
        # 创建上下文
        if context is None:
            context = CodeGenContext(
                ir_module=ir_module,
            )

        lines = []
        for stmt in statements:
            stmt_code = self.generate_statement(stmt, context)
            if stmt_code:
                lines.append(stmt_code)

        # 检查是否需要添加默认返回语句
        if return_type and return_type != "void" and return_type != "None":
            has_return = self._has_return_in_all_paths(lines)
            if not has_return:
                lines.append("return {};")

        return "\n    ".join(lines)

    def _has_return_in_all_paths(self, lines: List[str]) -> bool:
        """检查是否所有执行路径都有返回语句

        Args:
            lines: 生成的代码行列表

        Returns:
            bool: 是否所有路径都有返回语句
        """
        code = "\n".join(lines)

        # 检查是否有直接的return语句（不在控制结构中）
        direct_return_lines = [
            line
            for line in lines
            if line.strip().startswith("return ")
            and not any(
                control + " (" in line or "} " + control in line
                for control in ["if", "else", "while", "for"]
            )
        ]

        if direct_return_lines:
            return True

        # 检查if-else-if链是否完整且每个分支都有返回
        if "if (" in code and "} else" in code:
            # 检查是否有最终的else分支（不是else if）
            # 通过检查最后一个"} else"是否后面跟着"if"来判断
            else_positions = []
            pos = 0
            while True:
                pos = code.find("} else", pos)
                if pos == -1:
                    break
                else_positions.append(pos)
                pos += 1

            # 检查最后一个"} else"是否是最终else（不是else if）
            has_final_else = False
            if else_positions:
                last_else_pos = else_positions[-1]
                after_else = code[last_else_pos + 6 :].strip()  # 6 = len("} else")
                has_final_else = after_else.startswith(
                    "{"
                ) and not after_else.startswith("{ if")

            if has_final_else:
                # 计算return语句数量
                return_count = code.count("return ")
                # 计算if分支数量（包括if和elif）
                if_count = code.count("if (")

                # 如果有最终else分支，return数量应该等于if分支数量
                # 因为最终else分支的return已经包含在return_count中
                # 而if_count包含了所有的if和else if
                return return_count >= if_count

        return False

    def _generate_node(self, node: "IRNode", context: CodeGenContext) -> EmitResult:
        """生成节点代码

        Args:
            node: IR节点
            context: 代码生成上下文

        Returns:
            EmitResult: 生成结果
        """
        # 使用新的调度器接口
        return self.registry.emit_code(node, context)

    def _default_emit(self, node: "IRNode", context: CodeGenContext) -> EmitResult:
        """默认代码生成

        Args:
            node: IR节点
            context: 代码生成上下文

        Returns:
            EmitResult: 生成结果
        """
        # 最后的回退：生成注释
        return EmitResult(
            code=f"/* Unsupported node type: {type(node).__name__} */",
            precedence=0,
        )


# 初始化全局注册表
def _initialize_global_registry():
    """初始化全局注册表"""
    registry = get_global_registry()
    if not registry.get_all_emitters():  # 只有在空的时候才注册
        # 自动导入并注册所有发射器
        import mcpy.codegen.emitters as emitters_module

        for emitter_name in emitters_module.__all__:
            emitter_class = getattr(emitters_module, emitter_name)
            emitter_instance = emitter_class()
            registry.register(emitter_instance)


# 全局代码生成器实例
_global_generator = None


def get_global_generator() -> CodeGenerator:
    """获取全局代码生成器

    Returns:
        CodeGenerator: 全局代码生成器
    """
    global _global_generator
    if _global_generator is None:
        _global_generator = CodeGenerator()
        _initialize_global_registry()

    return _global_generator


def generate_expression(
    expr: "IRNode",
    parent_precedence: int = 100,
    in_assignment: bool = False,
    ir_module: Optional["IRModule"] = None,
) -> str:
    """生成表达式代码（便利函数）

    Args:
        expr: 表达式IR节点
        parent_precedence: 父表达式优先级
        in_assignment: 是否在赋值语句中
        ir_module: IR模块

    Returns:
        str: 生成的C++表达式代码
    """
    return get_global_generator().generate_expression(
        expr,
        context=None,
        parent_precedence=parent_precedence,
        in_assignment=in_assignment,
        ir_module=ir_module,
    )


def generate_statement(
    stmt: "IRNode",
    ir_module: Optional["IRModule"] = None,
) -> str:
    """生成语句代码（便利函数）

    Args:
        stmt: 语句IR节点
        ir_module: IR模块

    Returns:
        str: 生成的C++语句代码
    """
    return get_global_generator().generate_statement(stmt, None, ir_module)
